#include "StdAfx.h"
#include "CaretInfo.h"
#include <assert.h>

CaretInfo::CaretInfo(int width, int height)
	:_point(),
	_info(),
	_width(width),
	_height(height)
{
	_isDisplayed = false;
	_isCreated = false;
	_cellWitdh = 0;
	_posInInfo = 0;
	_lastAction = ACTION_NONE;
	_acceptedChars[VK_OEM_PERIOD] = _T('.');
	_acceptedChars[VK_DECIMAL] = _T('.');
	_acceptedChars[VK_OEM_COMMA] = _T(',');
	_acceptedChars[VK_NUM_PAD_0] = _T('0');
	_acceptedChars[VK_NUM_PAD_1] = _T('1');
	_acceptedChars[VK_NUM_PAD_2] = _T('2');
	_acceptedChars[VK_NUM_PAD_3] = _T('3');
	_acceptedChars[VK_NUM_PAD_4] = _T('4');
	_acceptedChars[VK_NUM_PAD_5] = _T('5');
	_acceptedChars[VK_NUM_PAD_6] = _T('6');
	_acceptedChars[VK_NUM_PAD_7] = _T('7');
	_acceptedChars[VK_NUM_PAD_8] = _T('8');
	_acceptedChars[VK_NUM_PAD_9] = _T('9');
}


CaretInfo::~CaretInfo(void)
{
}

void CaretInfo::Create(CWnd* wnd)
{
	_wnd = wnd;
	ASSERT(_wnd != NULL);
	if (!_isCreated)
		_wnd->CreateSolidCaret(_width,_height);
}

void CaretInfo::Destroy()
{
	Hide();
	if (_isCreated)
	{
		DestroyCaret();
		_isCreated = false;
	}
}

void CaretInfo::SetPosition(bool bShow, const CPoint* point)
{
	if (!_isCreated)
	{
		_wnd->CreateSolidCaret(_width,_height);
		_isCreated = true;
	}
	_isDisplayed = true;
	if (point)
	{
		_point = *point;
		CPaintDC dc(_wnd);
		CSize size = dc.GetTextExtent(_info);
		_point.x+= size.cx + (_cellWitdh-size.cx)/2;
		_wnd->SetCaretPos(_point);
	}
	if (bShow)
		_wnd->ShowCaret();
}

CPoint& CaretInfo::Position()
{
	return _point;
}

void CaretInfo::Hide()
{
	if (_isDisplayed)
	{
		_wnd->HideCaret();
		_isDisplayed = false;
	}
}

void CaretInfo::SetInfo( const int cellWidth, const CString* strInfo )
{
	_cellWitdh = cellWidth;
	if (strInfo)
	{
		_info = *strInfo;
		_posInInfo = strInfo->GetLength();
	}
}

CString& CaretInfo::Info()
{
	return _info;
}

void CaretInfo::SetCellWidth(const int cellWidth)
{
	_cellWitdh = cellWidth;
}

void CaretInfo::Update( CDC* dc,UINT action )
{
	CSize size = dc->GetTextExtent(_info);
	_lastAction = action;
	
	switch (action)
	{
	case VK_BACK:
		{
			_info.Delete(_info.GetLength()-1);
			_point.x+= dc->GetTextExtent(_info).cx - size.cx;
			_wnd->RedrawWindow();
		}
		break;
	case VK_HOME:
		{
			if (_posInInfo > 0)
			{
				CString tmpInfo = _info.Mid(0,_posInInfo);
				_point.x -= dc->GetTextExtent(tmpInfo).cx;
				_posInInfo = 0;
			}
		}
		break;
	case VK_END:
		{
			if (_posInInfo < _info.GetLength())
			{
				CString tmpInfo = _info.Mid(0,_posInInfo);
				_point.x += size.cx - dc->GetTextExtent(tmpInfo).cx;
				_posInInfo = _info.GetLength();
			}
		}
		break;
	case VK_LEFT:
		if (_posInInfo > 0)
		{
			CString tmpInfo = _info.Mid(_posInInfo-1,1);
			_point.x -= dc->GetTextExtent(tmpInfo).cx;
			--_posInInfo;
		}
		break;
	case VK_RIGHT:
		if (_posInInfo < _info.GetLength())
		{
			CString tmpInfo = _info.Mid(_posInInfo,1);
			_point.x += dc->GetTextExtent(tmpInfo).cx;
			++_posInInfo;
		}
		break;
	case VK_DELETE:
		{
			_info.Delete(_posInInfo);
			_wnd->RedrawWindow();
		}
		break;
	case ACTION_PAINT:
		{
			int dx = 0;
			if (_posInInfo > 0)
			{
				CString tmpInfo = _info.Mid(0,_posInInfo);
				dx = dc->GetTextExtent(tmpInfo).cx;
			}
			dc->TextOut(_point.x-dx,_point.y ,_info);
		}		
		break;
	case ACTION_RESIZE:
		_point.x+=(_cellWitdh-size.cx)/2 + size.cx;
		break;
	case VK_RETURN:
		::SendMessage(*_wnd,WM_KILLFOCUS,VK_RETURN,NULL);
		break;
	default:
		if (isalnum(action) || (action = _acceptedChars[action]))
		{
			CString strChar;
			strChar.Format(_T("%c"),action);
			CSize charSize = dc->GetTextExtent(strChar);
			_point.x += charSize.cx;
			_info+= strChar;
			_wnd->RedrawWindow();
		}
		break;
	}

	_wnd->SetCaretPos(_point);
}

bool CaretInfo::IsDisplayed()
{
	return _isDisplayed;
}

int CaretInfo::Action()
{
	return _lastAction;
}